#ifndef _FRAMEWORK_USBCAN_H_
#define _FRAMEWORK_USBCAN_H_

#include "Defs.h"
#include "Ican.h"

#include <memory>
#include <thread>
#include <atomic>
#include <vector>
#include <string>
#include <functional>

namespace zlg
{

class UsbCan : public ICan
{
public:
    UsbCan();
    UsbCan(int deviceType, int device, int channel, const BaudrateDef& baudrate, const UsbCanAbitDef usbAbit, const UsbCanDbitDef usbDbit, bool resistanceEnable);                                 //使用正常波特率
    UsbCan(int deviceType, int device, int channel, const std::string& customBaudrate, bool resistanceEnable);   //使用自定义波特率，自定义波特率需要使用baudcal工具生成
    ~UsbCan() override;

    //ICan
    OperationResult OpenCan() override;
    OperationResult CloseCan() override;
    bool IsDeviceOnLine() override;
    OperationResult SendCanMsg(const uint32_t canId, const SendType& sendType, const std::vector<uint8_t>& data) override;
    OperationResult SendCanfdMsg(const uint32_t canId, const SendType& sendType, const std::vector<uint8_t>& data) override;
    void reigsterListenerCb(std::function<void(ZCAN_Receive_Data*)>) override;
    //ICan

    void configCanDevice(int deviceType, int device, int channel, const BaudrateDef& baudrate, const UsbCanAbitDef usbAbit, const UsbCanDbitDef usbDbit, bool resistanceEnable);
    void configCanDevice(int deviceType, int device, int channel, const std::string& customBaudrate, bool resistanceEnable);

    static constexpr auto USBCAN_FD_200U = 9;

private:
    OperationResult openDevice();
    OperationResult initCan();
    OperationResult startCan();
    OperationResult resetCan();
    OperationResult closeCan();
    std::unique_ptr<ZCAN_Transmit_Data> buildCanFrame(const uint32_t canId, const SendType& sendType, const std::vector<uint8_t>& data);
    OperationResult sendData(std::unique_ptr<ZCAN_Transmit_Data> canFrame);
    std::unique_ptr<ZCAN_TransmitFD_Data> buildCanfdFrame(const uint32_t canId, const SendType& sendType, const std::vector<uint8_t>& data, bool canfdBRS);
    OperationResult sendData(std::unique_ptr<ZCAN_TransmitFD_Data> canFrame);
    bool SetCustomBaudrate();
    bool SetBaudrate();
    bool SetCanfdBaudrate();
    bool SetResistanceEnable();
//    UINT WINAPI OnDataRecv( LPVOID data );
    void recvDataProcess();
    void onRecvData();

    DEVICE_HANDLE                   itsDeviceHandle;
    CHANNEL_HANDLE                  itsChannelHandle;
    int                             itsChannelIndex;
    int                             itsDeviceIndex;
    int                             itsDeviceTypeIndex;
    std::atomic<uint8_t>            itsStatus;
    std::string                     itsCustomBaudrate;
    BaudrateDef                     itsBaudrate;
    UsbCanAbitDef                   itsUsbCanAbitDef;
    UsbCanDbitDef                   itsUsbCanDbitDef;
    bool                            itsResistanceEnable;
    std::unique_ptr<std::thread>    itsRecvThread;
    std::vector<std::function<void(ZCAN_Receive_Data*)>> itsRecvCbs;
//    std::string   itsAccCode; //验收码
//    std::ctring   itsAccMask;   //屏蔽码

    static constexpr auto NORMAL_WORK_MODE = 0; //正常工作模式
    static constexpr auto LISTEN_ONLY_WORK_MODE = 1;//只听工作模式
    static constexpr auto SINGLE_WAVE_FILTER = 0; //单波过滤
    static constexpr auto DOUBLE_WAVE_FILTER = 1;//双波过滤
    static constexpr auto CLOSE   = 0x00;
    static constexpr auto IDLE    = 0x01;
    static constexpr auto RUNNING = 0x02;
    static constexpr auto CAN_FRAME_MAX_SIZE = 8;
    static constexpr auto CANFD_FRAME_MAX_SIZE = 64;
};

}


#endif
